function result = sft(signal, N, B, L, d, K, sigma_vec, omega, G, G_hat)
%%
% 函数名：result = sft(signal, N, B, L, d, K, sigma_vec, omega, G, G_hat)
% 功  能：对稀疏信号进行稀疏傅里叶（sparse fourier transform）变换
% 参  数：
%       signal：需要进行变换的原信号
%       N：信号点数
%       B：分筐数
%       L：外循环次数
%       d：提取系数比例
%       K：稀疏度，即原信号中有用频率的个数
%       sigma_vec：频谱重排随机因子和其关于模 N 的倒数
%       omega：滤波器点数
%       G：平坦窗滤波器
%       G_hat：幅值估计滤波器
% 返回值：
%       result：变换后的频域结果
%
% 注：无
%%

    Z = zeros(L, N);        % 存储每次估值循环中得到的幅值
    result = zeros(N, 1);   % 存储最终的估计结果

    for i = 1:L
        
        % 进行频谱重排
        permuted = permute_signal(signal, N, omega, sigma_vec(1, i));
        
        % 重排后的信号与窗函数在时域上相乘
        % 只与 omega 有关，而非全部相乘
        % 提高速度的方式之一
        permuted = permuted .* G;

        % 进行降采样 fft
        F_desamp_signal = desample_fft(permuted, B, omega);
        
        % 从降采样后的结果中取出有用值的坐标估计值
        % ********************************************************************
        %                           位置一
        % F_desamp_signal 和 z_hat 一样吗？
        % 答：不一样。如果不镜像对称，会存在频偏的问题
        % 测试发现，如果将该句注释，再将位置二的语句注释，不会发生频移，但幅值趋势
        % 会发生较大错误
        % z_hat = circshift(flipud(F_desamp_signal), 1);
        % ********************************************************************
        z_hat = F_desamp_signal;
        [~, J] = sort(abs(z_hat), 'descend');
        J = J(1:d*K);
        
        % 对坐标估计值进行反哈希映射，并得到幅值的估计值
        [est_index, est_value] = inverse_hash_map(d, K, N, B, sigma_vec(2, i), J, z_hat, G_hat);
        Z(i, est_index) = est_value;
    end

    temp_x_hat = sum(Z ~= 0);
    [~, x_hat_index] = sort(temp_x_hat, 'descend');
    x_hat_index = x_hat_index(1:K); % 从估计序列中选取 K 个最大值所在的坐标，作为估计得到的坐标值

    % 遍历估计坐标值
    for i = 1:K 
        x_hat_idx_i = x_hat_index(i);
        re = real(Z(:, x_hat_idx_i));
        im = imag(Z(:, x_hat_idx_i));
        re = median(re);
        im = median(im);

        % ********************************************************************
        %                           位置二
        % 如果位置一处的语句没有被注释，则该语句也不应该被注释，因为位置一的语句会
        % 导致频率分量垂直翻转，因此需要该语句纠正这一翻转
        % 不过有一说一，里面用到的理论知识或许很有意思？
        % x_hat_idx_i = mod(N-x_hat_idx_i+1, N) + 1;
        % ********************************************************************
        num = re + im * 1i;
        a = angle(num) + 0.296108836078530; % 相位修正，原因不明
        m = abs(num);
        num = m * exp(a * 1i);

        result(x_hat_idx_i) = num;
    end

end